import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'http_global.dart';
import 'interceptor/http_dio_logger_interceptor.dart';
import 'interceptor/http_error_interceptor.dart';
import 'interceptor/http_parameter_sign_interceptor.dart';
import 'interceptor/http_response_body_interceptor.dart';

class Http {
  static Http get instance => _getInstance();

  // 静态私有成员，没有初始化
  static Http? _instance;

  // 工厂模式 : 单例公开访问点
  factory Http() => _getInstance();

  // 静态、同步、私有访问点
  static Http _getInstance() {
    return _instance ??= Http._init();
  }

  late Dio dio;

  final CancelToken _cancelToken = CancelToken();

  // 私有构造函数
  Http._init() {
    // BaseOptions、Options、RequestOptions 都可以配置参数，优先级别依次递增，且可以根据优先级别覆盖参数
    BaseOptions options = BaseOptions(
      baseUrl: HttpGlobal.baseUrl,
      connectTimeout: const Duration(seconds: HttpGlobal.connectTimeout),
      sendTimeout: const Duration(seconds: HttpGlobal.sendTimeout),
      receiveTimeout: const Duration(seconds: HttpGlobal.receiveTimeout),
    );
    dio = Dio(options);
    dio.interceptors.add(HttpResponseBodyInterceptor());
    //错误拦截器
    dio.interceptors.add(HttpErrorInterceptor());
    //cookie处理
    //dio.interceptors.add(HttpCookieInterceptor());
    //公共参数验签
    dio.interceptors.add(HttpParameterSignInterceptor());
    if (kDebugMode) {
      //日志拦截器
      dio.interceptors.add(
        PrettyDioLogger(
          requestHeader: true,
          requestBody: true,
          responseBody: true,
          responseHeader: false,
          error: true,
          compact: false,
        ),
      );
    }
    //_addCookie();
  }

  // /// 指定公共参数
  // /// [baseUrl] 地址前缀
  // /// [connectTimeout] 连接超时赶时间
  // /// [receiveTimeout] 接收超时赶时间
  // /// [interceptors] 基础拦截器
  // void getHttpDio(
  //     {String? baseUrl,
  //     int? connectTimeout,
  //     int? receiveTimeout,
  //     List<Interceptor>? interceptors}) {
  //   dio.options = dio.options.copyWith(
  //       baseUrl: baseUrl,
  //       connectTimeout: Duration(seconds: connectTimeout ?? 0),
  //       receiveTimeout: Duration(seconds: receiveTimeout ?? 0),
  //       contentType: 'application/json; charset=utf-8',
  //       headers: {
  //         "Accept": "application/json",
  //       });
  // }

  /// 设置headers
  void setHeaders(Map<String, dynamic> map) {
    dio.options.headers.addAll(map);
  }

  ///取消请求
  ///同一个cancel token 可以用于多个请求，当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
  ///所以参数可选
  void cancelRequests({CancelToken? token}) {
    token ?? _cancelToken.cancel("cancelled");
  }

  /// 读取本地配置
  Map<String, dynamic>? getAuthorizationHeader() {
    Map<String, String> headers;
    String accessToken = "";
    headers = {
      "Authorization": 'Bearer $accessToken',
    };
    return headers;
  }

  ///创建Cookie
  // Future<CookieManager> getCookie() async {
  //   Directory appDocDir = await getApplicationDocumentsDirectory();
  //   String appDocPath = appDocDir.path;
  //   PersistCookieJar cj = PersistCookieJar(
  //       ignoreExpires: true, storage: FileStorage("$appDocPath/.cookies/"));
  //   KLog.d("创建Cookie Cookie保存地址：$appDocPath");
  //   return CookieManager(cj);
  // }

  ///添加Cookie
  // void _addCookie() async {
  //   dio.interceptors.add(await getCookie());
  // }

  ///删除Cookie
  // void deleteCookieAll() async {
  //   CookieManager cookieManager = await getCookie();
  //   cookieManager.cookieJar.deleteAll();
  //   KLog.d("删除所有Cookie成功");
  // }

  ///删除指定Cookie
  // void deleteCookie(Uri uri) async {
  //   CookieManager cookieManager = await getCookie();
  //   cookieManager.cookieJar.delete(uri);
  //   KLog.d("删除指定Cookie uri：$Uri");
  // }

  ///get 操作
  Future get(
    String path, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    bool noCache = !HttpGlobal.cacheEnable, //是否开启缓存
    bool cacheDisk = false, //是否开启磁盘缓存
    bool refresh = false, //是否刷新缓存
    String? cacheKey, //缓存key
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions = requestOptions.copyWith(extra: {
      "refresh": refresh,
      "noCache": noCache,
      "cacheKey": cacheKey,
      "cacheDisk": cacheDisk,
    });
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    Response response;
    response = await dio.get(path,
        queryParameters: params,
        options: requestOptions,
        cancelToken: cancelToken ?? _cancelToken);
    return response;
  }

  ///  post 操作
  Future post(
    String path, {
    Map<String, dynamic>? params,
    data,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    var response = await dio.post(path,
        data: data,
        queryParameters: params,
        options: requestOptions,
        cancelToken: cancelToken ?? _cancelToken);
    return response;
  }

  /// put 操作
  Future put(
    String path, {
    data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    var response = await dio.put(path,
        data: data,
        queryParameters: params,
        options: requestOptions,
        cancelToken: cancelToken ?? _cancelToken);
    return response.data;
  }

  /// patch 操作
  Future patch(
    String path, {
    data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    var response = await dio.patch(path,
        data: data,
        queryParameters: params,
        options: requestOptions,
        cancelToken: cancelToken ?? _cancelToken);
    return response.data;
  }

  /// delete 操作
  Future delete(
    String path, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = options ?? Options();

    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    var response = await dio.delete(path,
        data: data,
        queryParameters: params,
        options: requestOptions,
        cancelToken: cancelToken ?? _cancelToken);
    return response.data;
  }

  /// post form 表单提交操作
  Future postForm(
    String path, {
    required Map<String, dynamic> params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    var response = await dio.post(path,
        data: FormData.fromMap(params),
        options: requestOptions,
        cancelToken: cancelToken ?? _cancelToken);
    return response.data;
  }

  ///文件上传
  Future upload(
    String path, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    Function(int count, int total)? onSendProgress,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    var response = await dio.post(
      path,
      data: data,
      queryParameters: params,
      options: requestOptions,
      cancelToken: cancelToken ?? _cancelToken,
      onSendProgress: onSendProgress,
    );
    return response.data;
  }

  ///文件下载
  Future download(
    String urlPath,
    dynamic savePath, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    Function(int count, int total)? onReceiveProgress,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions = requestOptions.copyWith(headers: authorization);
    }
    var response = await dio.download(
      urlPath,
      savePath,
      data: data,
      queryParameters: params,
      options: requestOptions,
      cancelToken: cancelToken ?? _cancelToken,
      onReceiveProgress: onReceiveProgress,
    );
    return response.data;
  }

  Future getRequest(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    CancelToken? cancelToken,
  }) async {
    var response = await dio.request(
      url,
      data: data,
      queryParameters: params,
      cancelToken: cancelToken ?? _cancelToken,
    );
    return response.data;
  }

  Future postRequest(
    String url,
    String method, {
    dynamic data,
    Map<String, dynamic>? params,
    CancelToken? cancelToken,
  }) async {
    Dio dioC = Dio();
    dioC.options = dio.options.copyWith(
      baseUrl: url,
    );
    dioC.interceptors.addAll(dio.interceptors);
    var response = await dioC.post(
      method,
      data: data,
      queryParameters: params,
      cancelToken: cancelToken ?? _cancelToken,
    );
    return response.data;
  }
}
